package info.niwota.frames;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.util.Config;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class PickDialog {
	private static final String TAG = "PickDialog";
	
	public static AlertDialog create(final Activity ctx, Intent target,
			final int title) {
		final AlertDialog.Builder b = new AlertDialog.Builder(ctx);
		b.setTitle(title);
		b.setIcon(R.drawable.ic_dialog_menu_generic);
		b.setInverseBackgroundForced(true);
		//
		final ResolveListAdapter adapter = new ResolveListAdapter(ctx, target);
		
		b.setAdapter(adapter, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				Intent ci = adapter.intentForPosition(which);
				if (ci != null) {
					ctx.startActivityForResult(ci, PhotoFrameActivity.RC_PICK);
				}
			}
		});
		final AlertDialog d = b.create();
		return d;
	}

	private static final class DisplayResolveInfo {
		ResolveInfo ri;
		CharSequence displayLabel;
		CharSequence extendedInfo;

		DisplayResolveInfo(ResolveInfo pri, CharSequence pLabel,
				CharSequence pInfo) {
			ri = pri;
			displayLabel = pLabel;
			extendedInfo = pInfo;
		}
	}

	private final static class ResolveListAdapter extends BaseAdapter {

		private PackageManager mPackageManager;
		private final Intent mIntent;
		private final LayoutInflater mInflater;

		private List<DisplayResolveInfo> mList;

		public ResolveListAdapter(Context context, Intent intent) {
			mIntent = new Intent(intent);
			mIntent.setComponent(null);
			mPackageManager = context.getPackageManager();

			mInflater = (LayoutInflater) context
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			init(intent);
		}

		private void init(Intent intent) {
			List<ResolveInfo> rList = mPackageManager.queryIntentActivities(
					intent, PackageManager.MATCH_DEFAULT_ONLY);
			if (Debug.DEBUG) {
				Log.d(TAG, "count: " + rList);
			}
			if (rList == null) {
				rList = new ArrayList<ResolveInfo> ();
			}
			int N = 0;
			if ((rList != null) && ((N = rList.size()) > 0)) {
				// Only display the first matches that are either of equal
				// priority or have asked to be default options.
				ResolveInfo r0 = rList.get(0);
				for (int i = 1; i < N; i++) {
					ResolveInfo ri = rList.get(i);
					if (Config.LOGV)
						Log.v("ResolveListActivity", r0.activityInfo.name + "="
								+ r0.priority + "/" + r0.isDefault + " vs "
								+ ri.activityInfo.name + "=" + ri.priority
								+ "/" + ri.isDefault);
					if (r0.priority != ri.priority
							|| r0.isDefault != ri.isDefault) {
						while (i < N) {
							rList.remove(i);
							N--;
						}
					}
				}
				//
				Intent webshot = new Intent(Intent.ACTION_GET_CONTENT);
				webshot.setClassName("info.niwota.frames", "info.niwota.frames.WebshotInstallActivity");
				List<ResolveInfo> installer = mPackageManager.queryIntentActivities(webshot, PackageManager.MATCH_DEFAULT_ONLY);
				rList.addAll(installer);
				if (Debug.DEBUG) {
					Log.d(TAG, "count: " + rList);
				}
				N += (installer == null ? 0 : installer.size()); //one and only one but just to be safe
				if (N > 1) {
					ResolveInfo.DisplayNameComparator rComparator = new ResolveInfo.DisplayNameComparator(
							mPackageManager);
					Collections.sort(rList, rComparator);
				}
				// Check for applications with same name and use application
				// name or
				// package name if necessary
				mList = new ArrayList<DisplayResolveInfo>();
				r0 = rList.get(0);
				int start = 0;
				CharSequence r0Label = r0.loadLabel(mPackageManager);
				for (int i = 1; i < N; i++) {
					if (r0Label == null) {
						r0Label = r0.activityInfo.packageName;
					}
					ResolveInfo ri = rList.get(i);
					CharSequence riLabel = ri.loadLabel(mPackageManager);
					if (riLabel == null) {
						riLabel = ri.activityInfo.packageName;
					}
					if (riLabel.equals(r0Label)) {
						continue;
					}
					processGroup(rList, start, (i - 1), r0, r0Label);
					r0 = ri;
					r0Label = riLabel;
					start = i;
				}
				// Process last group
				processGroup(rList, start, (N - 1), r0, r0Label);
			}
		}

		private void processGroup(List<ResolveInfo> rList, int start, int end,
				ResolveInfo ro, CharSequence roLabel) {
			// Process labels from start to i
			int num = end - start + 1;
			if (num == 1) {
				// No duplicate labels. Use label for entry at start
				mList.add(new DisplayResolveInfo(ro, roLabel, null));
			} else {
				boolean usePkg = false;
				CharSequence startApp = ro.activityInfo.applicationInfo
						.loadLabel(mPackageManager);
				if (startApp == null) {
					usePkg = true;
				}
				if (!usePkg) {
					// Use HashSet to track duplicates
					HashSet<CharSequence> duplicates = new HashSet<CharSequence>();
					duplicates.add(startApp);
					for (int j = start + 1; j <= end; j++) {
						ResolveInfo jRi = rList.get(j);
						CharSequence jApp = jRi.activityInfo.applicationInfo
								.loadLabel(mPackageManager);
						if ((jApp == null) || (duplicates.contains(jApp))) {
							usePkg = true;
							break;
						} else {
							duplicates.add(jApp);
						}
					}
					// Clear HashSet for later use
					duplicates.clear();
				}
				for (int k = start; k <= end; k++) {
					ResolveInfo add = rList.get(k);
					if (usePkg) {
						// Use application name for all entries from start to
						// end-1
						mList.add(new DisplayResolveInfo(add, roLabel,
								add.activityInfo.packageName));
					} else {
						// Use package name for all entries from start to end-1
						mList.add(new DisplayResolveInfo(add, roLabel,
								add.activityInfo.applicationInfo
										.loadLabel(mPackageManager)));
					}
				}
			}
		}

		public Intent intentForPosition(int position) {
			if (mList == null) {
				return null;
			}

			Intent intent = new Intent(mIntent);
			//intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
			//		| Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
			ActivityInfo ai = mList.get(position).ri.activityInfo;
			intent.setComponent(new ComponentName(
					ai.applicationInfo.packageName, ai.name));
			return intent;
		}

		public int getCount() {
			return mList != null ? mList.size() : 0;
		}

		public Object getItem(int position) {
			return position;
		}

		public long getItemId(int position) {
			return position;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			View view;
			if (convertView == null) {
				view = mInflater.inflate(R.layout.resolve_list_item, parent,
						false);
			} else {
				view = convertView;
			}
			bindView(view, mList.get(position));
			return view;
		}

		private final void bindView(View view, DisplayResolveInfo info) {
			TextView text = (TextView) view.findViewById(R.id.text1);
			TextView text2 = (TextView) view.findViewById(R.id.text2);
			ImageView icon = (ImageView) view.findViewById(R.id.icon);
			text.setText(info.displayLabel);
			if (info.extendedInfo != null) {
				text2.setVisibility(View.VISIBLE);
				text2.setText(info.extendedInfo);
			} else {
				text2.setVisibility(View.GONE);
			}
			icon.setImageDrawable(info.ri.loadIcon(mPackageManager));
		}

	}
}
